﻿/* The .Net Multi-Core Library by Cory Dambach */

using System;
using System.Collections.Generic;
using System.Threading;

namespace DambachMulti.DataStructures
{
	/// <summary>
	/// A homogenous self-redimming array, that utilizes parallel processing methods, must use reference types for the time being
	/// </summary>
	/// <see cref="http://msdn2.microsoft.com/en-us/library/ms379570(VS.80).aspx#datastructures20_1_topic2" />
	/// <typeparam name="T">The Type of the Elements in the ArraySequence</typeparam>
	public class Sequence<T> : System.Collections.Generic.List<T>, IFunctional<T> //I know it looks wierd but, from msdn: The List: a Homogeneous, Self-Redimensioning ArraySequence
	{
		//yuck, I know its not the best formatting but it will have to do...
		public Sequence()						: base(			) {}
		public Sequence(int cap)				: base( cap		) {}
		public Sequence(IEnumerable<T> ienum)	: base( ienum	) {}
		
		/// <summary>
		/// Apply a function to every element in a sequence
		/// </summary>
		/// <param name="method">The method to apply to the sequence</param>
		public void Map( Action<T> method )
		{
			//Is using smart pooled for right now
			Multi.For( 0, this.Count, 1, delegate( int i ) {
          		method( this[i] ); //apply the mapped method in parallel to every element in the list
          	}, 2 );
		}

		/// <summary>
		/// Reduce a sequence to a single value, warning! reducer should not modify result, NOT WORKING WELL YET
		/// </summary>
		[Obsolete("Works...But is slower than regular method...TODO: Reimplement.")]
		public T Reduce( Reducer<T> reducer )
		{			
			if( this.Count == 0 )
				throw new Exception( "Cannot reduce an empty Sequence." );
		
			Object	nullObj	= new Object(); //represents null for value types
			Object	result	= nullObj;		//symbolize null for me now!
			T		current = default(T);	//set the initial result equal to the first value in the list
			Multi.For( 0, this.Count, delegate( int i )
			{
				T		next	= this[i]; //this is a really convoluted implementation...but short...so If its efficient, I'll clean up the var names		
				Object	tmp		= reducer( current, next );
				if( tmp != null )
					Interlocked.Exchange( ref result, tmp );
				if( result == nullObj )
					return; //basically a continue statement in this context
				current = (T)result; //recast the object to its original type, works for value types too
			} );
			if( nullObj == result )
				return default(T);
			return (T)result;
		}

		/// <summary>
		/// Eliminate all elements in a sequence that pass the predicate
		/// TODO: these are implemented in serial in other places...Should I override those functions???
		/// </summary>
		public void Filter( Predicate<T> conditional )
		{
			Multi.For( 0, this.Count, delegate( int i ) {
				if( conditional( this[i] ) == true ) {
					lock( this ) { //synchronize the current object, because we are working in parallel (might not be a great idea
						this.RemoveAt( i ); //remove the offending item
					}
				}
			} );
		}
	}
}
